﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Nature
{

    /// <summary>
    /// Represents an algorithm calculating the functional linear decomposition
    /// </summary>
    public interface IFuncBasisResolver
    {
        /// <summary>
        /// Finds the functional basis decomposition coefficients
        /// </summary>
        /// <param name="function">The function to be represented in the form of the functional basis</param>
        /// <param name="domain">Collection of the independent variable values (x-domain)</param>
        /// <param name="basis">Collection of functions representing the functional basis</param>
        /// <returns>Linear decomposition of the given function</returns>
        FuncBasisDecomposition Decompose(Func<double, double> function, IEnumerable<double> domain, IEnumerable<Func<double, double>> basis);
    }


    /// <summary>
    /// Linear decomposition of a function
    /// </summary>
    public class FuncBasisDecomposition
    {
        #region Private Fields
        ReadOnlyArray<Func<double, double>> m_basis;
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        ReadOnlyArray<double> m_coef; 
        #endregion

        /// <summary>
        /// Initializes a new instance of the FuncBasisDecomposition class.
        /// </summary>
        /// <param name="basis">Functional basis</param>
        /// <param name="coef">Decomposition coefficients</param>
        public FuncBasisDecomposition(ReadOnlyArray<Func<double, double>> basis, ReadOnlyArray<double> coef)
        {
            m_basis = basis;
            m_coef = coef;
        }

        /// <summary>
        /// Decomposition coefficients
        /// </summary>
        public ReadOnlyArray<double> Coefficients { get { return m_coef; } }

        /// <summary>
        /// Functional basis
        /// </summary>
        public ReadOnlyArray<Func<double, double>> Basis { get { return m_basis; } }

        /// <summary>
        /// Calculates the function value (approximate) for the given variable using this functional decomposition
        /// </summary>
        /// <param name="value">Independent variable</param>
        /// <returns>Function value avaluated using this decomposition</returns>
        public double Calculate(double value)
        {
            double sum = 0.0;
            for (int i = 0; i < m_basis.Length; ++i)
            {
                sum += m_coef[i] * m_basis[i](value);
            }
            return sum;
        }
    }
}
